﻿using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEngine.EventSystems;
using Newtonsoft.Json;

public static class CommonUtil
{
    public static Color32 toColor32(this uint v)
    {
		Color32 c = new Color32((byte)((v >> 24) & 0xff), (byte)((v >> 16) & 0xff), (byte)((v >> 8) & 0xff), (byte)(v & 0xff));
        return c;
    }

	public static Color32 toColor32(this int v)
	{
		Color32 c = new Color32((byte)((v >> 24) & 0xff), (byte)((v >> 16) & 0xff), (byte)((v >> 8) & 0xff), (byte)(v & 0xff));
		return c;
	}

    public static Color toColor(this uint v)
    {
		float t = 1 / 255f;
		Color c = new Color(((v >> 24) & 0xff) * t, ((v >> 16) & 0xff) * t, ((v >> 8) & 0xff) * t, (v & 0xff) * t);
		return c;
    }

	public static Color toColor(this int v)
	{
		float t = 1 / 255f;
		Color c = new Color(((v >> 24) & 0xff) * t, ((v >> 16) & 0xff) * t, ((v >> 8) & 0xff) * t, (v & 0xff) * t);
		return c;
	}

    public static string md5(string input)
    {
        // step 1, calculate MD5 hash from input
        MD5 md5 = MD5.Create();
        byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
        byte[] hash = md5.ComputeHash(inputBytes);

        // step 2, convert byte array to hex string
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("X2"));
        }
        return sb.ToString();
    }

    public static string md5(byte[] inputBytes)
    {
        // step 1, calculate MD5 hash from input
        MD5 md5 = MD5.Create();
        byte[] hash = md5.ComputeHash(inputBytes);

        // step 2, convert byte array to hex string
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("X2"));
        }
        return sb.ToString();
    }

    public static string cachePath
    {
        get
        {
//            if(Application.isEditor)
//            {
//                return Application.persistentDataPath;
//            }
//            else if(Application.platform == RuntimePlatform.Android)
//            {
//                #if UNITY_ANDROID && !UNITY_EDITOR
//                //return ChatPluginAndroid.Instance.GetWritablePath() + "/files";
//                #endif
//            }
//            return Application.temporaryCachePath;

            if (Application.platform == RuntimePlatform.IPhonePlayer)
            {
                return Application.temporaryCachePath;
            }

            return Application.persistentDataPath;
        }
    }

    public static string addSuffixToFileName(string path, string suffix)
    {
        string dir = Path.GetDirectoryName(path);
        string fileName = Path.GetFileNameWithoutExtension(path);
        string extName = Path.GetExtension(path);

        string temp = fileName + suffix + extName;
        if (!string.IsNullOrEmpty(dir))
        {
            temp = dir + "/" + temp;
        }

        return temp;
    }

    public static string fileToString(string filePath)
    {
        if(!File.Exists(filePath))
        {
            return null;
        }

        return File.ReadAllText(filePath);
    }

    public static bool bytesToFile(string filePath, byte[] bytes)
    {
#if !WEBPLAYER
        try
        {
        #if UNITY_EDITOR_WIN
            if(File.Exists(filePath))
            {
                new FileInfo(@filePath).Attributes = FileAttributes.Normal; 
            }
        #endif 
            File.WriteAllBytes(filePath, bytes);
        }
        catch(System.Exception e)
        {
            Debug.LogException(e);
            CommonUtil.Delete(filePath);
            return false;
        }
#endif
        return true;
    }

    public static string[] GetFiles(string dir, string findStr, SearchOption option)
    {
        try
        {
            string[] files = Directory.GetFiles(dir, findStr, option);
            return files;
        }
        catch(System.Exception e)
        {
            Debug.LogException(e);
        }
        return null;
    }

    public static bool Exists(string path)
    {
        return File.Exists(path) || Directory.Exists(path);
    }

    public static bool Copy(string inFilePath, string outFilePath)
    {
#if !WEBPLAYER
        try
        {
            File.Copy(inFilePath, outFilePath, true);
        }
        catch(DirectoryNotFoundException e2)
        {
            string dir = Path.GetDirectoryName(outFilePath);
            Directory.CreateDirectory(dir);
            return Copy(inFilePath, outFilePath);
        }
        catch(System.Exception e)
        {
            Debug.LogException(e);
            CommonUtil.Delete(outFilePath);
            return false;
        }
#endif
        return true;
    }

    public static byte[] fileToBytes(string filePath)
    {
        if(!File.Exists(filePath))
        {
            return null;
        }
        
        return File.ReadAllBytes(filePath);
    }

    public static bool stringToFile(string filePath, string str)
    {
#if !WEBPLAYER
        try
        {
            File.WriteAllText(filePath, str);
        }
        catch(DirectoryNotFoundException e2)
        {
            string dir = Path.GetDirectoryName(filePath);
            Directory.CreateDirectory(dir);
            return stringToFile(filePath, str);
        }
        catch(System.Exception e)
        {
            Debug.LogException(e);
            CommonUtil.Delete(filePath);
            return false;
        }
#endif
        return true;
    }

    public static string StreamToString(Stream srcStream)
    {
        StreamReader reader = new StreamReader(srcStream);
        return reader.ReadToEnd();
    }

    public static long GetFileSize(string filePath)
    {
        try
        {
            FileStream fileStream = File.OpenRead(filePath);
            long len = fileStream.Length;
            fileStream.Close();
            return len;
        }
        catch(System.Exception e)
        {
            Debug.LogException(e);
        }
        return 0;
    }
    
    public static void Delete(string filePath)
    {
        if(Directory.Exists(filePath))
        {
            Directory.Delete(filePath, true);
        }
        else if(File.Exists(filePath))
        {
            File.Delete(filePath);
        }
    }

    public static void CreateDir(string dir)
    {
        Directory.CreateDirectory(dir);
        //#if UNITY_IOS
        //      PlatformInvoke.Instance.AddSkipBackupDir(dir);
        //#endif
    }

    public static void CopyDirectory(string srcDir, string tgtDir)
    {
        DirectoryInfo source = new DirectoryInfo(srcDir);
        DirectoryInfo target = new DirectoryInfo(tgtDir);

        if (target.FullName.StartsWith(source.FullName, StringComparison.CurrentCultureIgnoreCase))
        {
            //throw new Exception("父目录不能拷贝到子目录！");
            return;
        }

        if (!source.Exists)
        {
            return;
        }

        if (!target.Exists)
        {
            target.Create();
        }

        FileInfo[] files = source.GetFiles();

        for (int i = 0; i < files.Length; i++)
        {
            File.Copy(files[i].FullName, target.FullName +  "/" + files[i].Name, true);
        }

        DirectoryInfo[] dirs = source.GetDirectories();

        for (int j = 0; j < dirs.Length; j++)
        {
            CopyDirectory(dirs[j].FullName, target.FullName + "/" + dirs[j].Name);
        }
    } 
    public static bool Move(string srcPath, string destPath)
    {
        if (srcPath == destPath)
        {
            return true;
        }

        Delete(destPath);

#if !WEBPLAYER
        try
        {
            if(Directory.Exists(srcPath))
            {
                Directory.Move(srcPath, destPath);
            }
            else if(File.Exists(srcPath))
            {
                File.Move(srcPath, destPath);
            }
            else
            {
                return false;
            }
        }
        catch(DirectoryNotFoundException e2)
        {
            string dir = Path.GetDirectoryName(destPath);
            Directory.CreateDirectory(dir);
            return Move(srcPath, destPath);
        }
        catch(System.Exception e)
        {
            Debug.LogException(e);
            if(!Directory.Exists(srcPath) && Directory.Exists(destPath))
            {
                Directory.Move(destPath, srcPath);
            }
            else if(!File.Exists(srcPath) && File.Exists(destPath))
            {
                File.Move(destPath, srcPath);
            }
            return false;
        }
#endif
        return true;
    }



    public static string toSizeString(float size, bool showGB = true)
    {
        string unit = null;
        float remain = 0;
        int de = 1024;
        if(size < de)
        {
            unit = "B";
        }

        if(unit == null)
        {
            remain = size % de;
            size /= de;
            if(size < de)
            {
                unit = "K";
            }
        }

        if (showGB)
        {
            if (unit == null)
            {
                remain = size % de;
                size /= de;
                if (size < de)
                {
                    unit = "M";
                }
            }

            if (unit == null)
            {
                remain = size % de;
                size /= de;
                if (size < de)
                {
                    unit = "G";
                }
            }
        }
        else
        {
            if (unit == null)
            {
                remain = size % de;
                size /= de;
                unit = "M";
            }
        }

        string format = null;
        if(remain < Mathf.Epsilon)
        {
            format = "{0:0}";
        }
        else
        {
            format = "{0:0.0}";
        }
        return string.Format(format, size)  + unit;

    }
    public static long GetTimestamp()
    {
        TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1);//ToUniversalTime()转换为标准时区的时间,去掉的话直接就用北京时间
        return (long)ts.TotalMilliseconds; //精确到毫秒
        //return (long)ts.TotalSeconds;//获取10位
    }

    public static T ObjectFromJsonFile<T>(string filePath)
    {
        string str = fileToString(filePath);
        if (str == null)
        {
            return default(T);
        }

        try
        {
            T t = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(str);
            return t;
        }
        catch(System.Exception e)
        {
            Debug.LogException(e);
        }
        return default(T);
    }

    public static void ObjectToJsonFile<T>(T t, string filePath)
    {
        if (t == null)
        {
            return;
        }

        string str = Newtonsoft.Json.JsonConvert.SerializeObject(t, Newtonsoft.Json.Formatting.Indented);
        stringToFile(filePath, str);
    }

    public static T[] FindObjectsOfType<T>()
    {
        GameObject[] objs = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
        List<T> l = new List<T>();
        for (int i = 0; i < objs.Length; i++)
        {
            T[] ts = objs[i].GetComponentsInChildren<T>();
            l.AddRange(ts);
        }

        return l.ToArray();
    }

    public static AppInfo GetAppInfo()
    {
        TextAsset appInfoAsset = Resources.Load<TextAsset>("app_info");
        return JsonConvert.DeserializeObject<AppInfo>(appInfoAsset.text);
    }
}